package com.cx.base.autoDoc.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import com.cx.base.autoDoc.annotations.AutoDocField;


/**
 * 自动生成接口文档--工具类
 * 通过Java反射机制，动态给对象属性赋值，并获取属性值
 * 
 * @author cenxi
 * @date 2015-11-11
 */
public class ClassRefUtil {   
     
    /** 
     * 取Bean的属性和值对应关系的MAP 
     * @param bean 
     * @return Map 
     */ 
    public static Map<String, String> getFieldValueMap(Object bean) {  
        Class<?> cls = bean.getClass();  
        Map<String, String> valueMap = new HashMap<String, String>();  
        // 取出bean里的所有方法  
        Method[] methods = cls.getDeclaredMethods();  
        Field[] fields = cls.getDeclaredFields();  
   
        for (Field field : fields) {  
            try {  
                String fieldType = field.getType().getSimpleName();  
                String fieldGetName = parGetName(field.getName());  
                if (!checkGetMet(methods, fieldGetName)) {  
                    continue;  
                }  
                Method fieldGetMet = cls.getMethod(fieldGetName, new Class[] {});  
                Object fieldVal = fieldGetMet.invoke(bean, new Object[] {});  
                String result = null;  
                if ("Date".equals(fieldType)) {  
                    result = fmtDate((Date) fieldVal);  
                } else {  
                    if (null != fieldVal) {  
                        result = String.valueOf(fieldVal);  
                    }  
                }  
                valueMap.put(field.getName(), result);  
            } catch (Exception e) {  
                continue;  
            }  
        }  
        return valueMap;  
   
    }  
   
    /** 
     * set属性的值到Bean 
     * @param bean 
     * @param valMap 
     */ 
    public static Object setFieldValue(Object bean) {
    	//防死循环
		if(PdfUtil.cycleTime < 0){
			return bean;
		}else{
			PdfUtil.cycleTime --;
		}
    	
        Class<?> cls = bean.getClass();  
        // 取出bean里的所有方法  
        Method[] methods = cls.getDeclaredMethods();  
        Field[] fields = cls.getDeclaredFields();  
   
        for (Field field : fields) {  
            try {
            	AutoDocField autoDocField = field.getAnnotation(AutoDocField.class);
            	
            	String fieldSetName = parSetName(field.getName());  
                if (!checkSetMet(methods, fieldSetName)) {  
                    continue;  
                }  
                Method fieldSetMet = cls.getMethod(fieldSetName, field.getType());
                String fieldType = field.getType().getSimpleName();
            	
                Class fieldClazz = field.getType();
                if(fieldClazz.isPrimitive() || ifBasicTypes(fieldClazz)){
                	 if ("String".equals(fieldType)) {  
 	                    fieldSetMet.invoke(bean, "abcdef");  
 	                } else if ("Date".equals(fieldType)) {
 	                    fieldSetMet.invoke(bean, new Date());  
 	                } else if ("Integer".equals(fieldType) || "int".equals(fieldType)) { 
 	                    fieldSetMet.invoke(bean, 0);  
 	                } else if ("Long".equalsIgnoreCase(fieldType)) {
 	                    fieldSetMet.invoke(bean, 0L);  
 	                } else if ("Double".equalsIgnoreCase(fieldType)) {
 	                    fieldSetMet.invoke(bean, 0.00);  
 	                } else if ("Boolean".equalsIgnoreCase(fieldType)) {
 	                    fieldSetMet.invoke(bean, true);  
 	                }else if ("BigDecimal".equalsIgnoreCase(fieldType)) {
 	                    fieldSetMet.invoke(bean, 0);  
 	                } else if ("List".equalsIgnoreCase(fieldType)) {
 	                	ParameterizedType pt = (ParameterizedType)field.getGenericType();
						Class ptClazz = (Class) pt.getActualTypeArguments()[0];
						
						Object resObj = ptClazz.newInstance();
	            		resObj = setFieldValue(resObj);
						
            			List<Object> resList = new ArrayList<Object>();
						resList.add(resObj);
						resList.add(resObj);
						fieldSetMet.invoke(bean, resList);
 	                } else {  
 	                    System.out.println("not supper type" + fieldType);  
 	                } 
                }else{
                	Object resObj = fieldClazz.newInstance();
            		resObj = setFieldValue(resObj);
        			fieldSetMet.invoke(bean, resObj);
                }
            } catch (Exception e) {  
                continue;  
            }  
        }  
        return bean;
    }  
    
    
	/**
	 * 判断是否基本类型
	 * */
	public static Boolean ifBasicTypes(Class clazz){
		
		String name = clazz.getName();
		
		if(name.indexOf("com.cx") > -1){
			return false;
		}else{
			return true;
		}
		
		 /*String fieldType = clazz.getSimpleName();
		   if ("String".equals(fieldType)) {  
			 return true;
         } else if ("Date".equals(fieldType)) { 
        	 return true;
         } else if ("Integer".equals(fieldType) || "int".equals(fieldType)) { 
        	 return true;
         } else if ("Long".equalsIgnoreCase(fieldType)) {
        	 return true;
         } else if ("Double".equalsIgnoreCase(fieldType)) {
        	 return true;
         } else if ("Boolean".equalsIgnoreCase(fieldType)) {
        	 return true;
         }else if("Float".equalsIgnoreCase(fieldType)){
        	 return true;
         }else if("Character".equalsIgnoreCase(fieldType)){
        	 return true;
         }else if("Byte".equalsIgnoreCase(fieldType)){
        	 return true;
         }else if("Short".equalsIgnoreCase(fieldType)){
        	 return true;
         }
		
		return false;*/
	}
	
   
    /** 
     * 格式化string为Date 
     * @param datestr 
     * @return date 
     */ 
    private static Date parseDate(String datestr) {  
        if (null == datestr || "".equals(datestr)) {  
            return null;  
        }  
        try {  
            String fmtstr = null;  
            if (datestr.indexOf(':') > 0) {  
                fmtstr = "yyyy-MM-dd HH:mm:ss";  
            } else {  
                fmtstr = "yyyy-MM-dd";  
            }  
            SimpleDateFormat sdf = new SimpleDateFormat(fmtstr, Locale.UK);  
            return sdf.parse(datestr);  
        } catch (Exception e) {  
            return null;  
        }  
    }  
    /** 
     * 日期转化为String 
     * @param date 
     * @return date string 
     */ 
    private static String fmtDate(Date date) {  
        if (null == date) {  
            return null;  
        }  
        try {  
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);  
            return sdf.format(date);  
        } catch (Exception e) {  
            return null;  
        }  
    }  
   
    /** 
     * 判断是否存在某属性的 set方法 
     * @param methods 
     * @param fieldSetMet 
     * @return boolean 
     */ 
    private static boolean checkSetMet(Method[] methods, String fieldSetMet) {  
        for (Method met : methods) {  
            if (fieldSetMet.equals(met.getName())) {  
                return true;  
            }  
        }  
        return false;  
    }  
    /** 
     * 判断是否存在某属性的 get方法 
     * @param methods 
     * @param fieldGetMet 
     * @return boolean 
     */ 
    private static boolean checkGetMet(Method[] methods, String fieldGetMet) {  
        for (Method met : methods) {  
            if (fieldGetMet.equals(met.getName())) {  
                return true;  
            }  
        }  
        return false;  
    }  
   
    /** 
     * 拼接某属性的 get方法 
     * @param fieldName 
     * @return String 
     */ 
    private static String parGetName(String fieldName) {  
        if (null == fieldName || "".equals(fieldName)) {  
            return null;  
        }  
        return "get" + fieldName.substring(0, 1).toUpperCase()  
                + fieldName.substring(1);  
    }  
    /** 
     * 拼接在某属性的 set方法 
     * @param fieldName 
     * @return String 
     */ 
    private static String parSetName(String fieldName) {  
        if (null == fieldName || "".equals(fieldName)) {  
            return null;  
        }  
        return "set" + fieldName.substring(0, 1).toUpperCase()  
                + fieldName.substring(1);  
    } 
 
}